#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "qcustomplot.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

   // ui->pushButton_2->setHidden(true);

    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(on_pushButton_3_clicked()));
    connect(ui->pushButton_4,SIGNAL(clicked()), timer, SLOT(stop()));
    connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),ui->label_11, SLOT(setText(QString)));
    connect(ui->doubleSpinBox_L1,SIGNAL(valueChanged(double)), this, SLOT(updateNumberForTau()));
    connect(ui->doubleSpinBox_L2,SIGNAL(valueChanged(double)), this, SLOT(updateNumberForTau()));
    connect(ui->doubleSpinBox_T,SIGNAL(valueChanged(double)), this, SLOT(updateNumberForTau()));
    connect(ui->spinBox,SIGNAL(valueChanged(int)), this, SLOT(updateNumberForTau()));
    this->updateNumberForTau();


    connect(ui->doubleSpinBox_c,SIGNAL(valueChanged(double)), this, SLOT(updateSR()));
    connect(ui->doubleSpinBox_ro,SIGNAL(valueChanged(double)), this, SLOT(updateSR()));
    connect(ui->doubleSpinBox_k,SIGNAL(valueChanged(double)), this, SLOT(updateSR()));
    connect(ui->doubleSpinBox_nu,SIGNAL(valueChanged(double)), this, SLOT(updateSR()));
    connect(ui->doubleSpinBox_gamma,SIGNAL(valueChanged(double)), this, SLOT(updateSR()));
    connect(ui->doubleSpinBox_L1,SIGNAL(valueChanged(double)), this, SLOT(updateSR()));
    connect(ui->doubleSpinBox_L2,SIGNAL(valueChanged(double)), this, SLOT(updateSR()));
    this->updateSR();

    table = new QTableWidget(0);
    table->setRowCount(3);
    table->setWindowTitle("Table");
    QStringList headers;
    headers.clear();
    headers.append("x_i");
    headers.append("u1_i");
    headers.append("u2_i");
    table->setVerticalHeaderLabels(headers);
    table->horizontalHeader()->hide();

    splineTable = new QTableWidget(0);
    splineTable->setColumnCount(5);
    splineTable->setWindowTitle("Test tasks");
    headers.clear();
    headers.append("i");
    headers.append("x_i");
    headers.append("u_i");
    headers.append("v_i");
    headers.append("|u_i-v_i|");
    splineTable->setHorizontalHeaderLabels(headers);
    splineTable->verticalHeader()->hide();
    splineTable->setColumnWidth(0,35);

    difference = new QCustomPlot();
    difference->setFixedSize(400,400);
    difference->show();
}

MainWindow::~MainWindow()
{
    timer->stop();
    delete table;
    delete splineTable;
    delete ui;
}

bool MainWindow::event(QEvent *mEvent)
{
    if (mEvent->type()==QEvent::Close)
    {
        timer->stop();
        table->close();
        splineTable->close();
        difference->close();
        this->close();
        return true;
    }
    return QMainWindow::event(mEvent);
}


void MainWindow::plotFunc(QVector<double>& x, QVector<double>& y, QPen color)
{
    ui->graphWidget->clearGraphs();
    ui->graphWidget->addGraph();

    ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->setData(x, y);
    // give the axes some labels:
    ui->graphWidget->xAxis->setLabel("x");
    ui->graphWidget->yAxis->setLabel("y");
    ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->setPen(color);
    //ui->graphWidget->xAxis->setRange(x[0]-0.5,x[x.size()+1]+0.5);
    //ui->graphWidget->yAxis->setRange(-2.5,2.5);
    //ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->rescaleAxes(true);
    //ui->graphWidget->replot();
}

void MainWindow::plotFunc2(QVector<double>& x, QVector<double>& y, QPen color)
{
    difference->clearGraphs();
    difference->addGraph();

    difference->graph(0)->setData(x, y);
    // give the axes some labels:
    difference->xAxis->setLabel("x");
    difference->yAxis->setLabel("y");
    difference->graph(0)->setPen(color);
    //ui->graphWidget->xAxis->setRange(x[0]-0.5,x[x.size()+1]+0.5);
    //ui->graphWidget->yAxis->setRange(-2.5,2.5);
    //ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->rescaleAxes(true);
    //difference->graph(0)->rescaleAxes();
    difference->replot();
}


void MainWindow::on_pushButton_3_clicked()
{
    ui->graphWidget->clearGraphs();


    if (currentIter==0)
    {
        for (int i=0; i<n+1; ++i)
        {
            //НУ
            u1[i] = ui->doubleSpinBox_u1_m1->value()*cos(ui->spinBox_m1->value()*M_PI*x[i]) +
                    ui->doubleSpinBox_u1_m2->value()*cos(ui->spinBox_m2->value()*M_PI*x[i]) +
                    ui->doubleSpinBox_u1_m3->value()*cos(ui->spinBox_m3->value()*M_PI*x[i]);
            u2[i] = ui->doubleSpinBox_u2_m1->value()*cos(ui->spinBox_m1->value()*M_PI*x[i]) +
                    ui->doubleSpinBox_u2_m2->value()*cos(ui->spinBox_m2->value()*M_PI*x[i]) +
                    ui->doubleSpinBox_u2_m3->value()*cos(ui->spinBox_m3->value()*M_PI*x[i]);
//            u1[i] = 3.0 + (cos(M_PI*x[i]))+ (cos(2*M_PI*x[i]))+ (cos(3*M_PI*x[i])); //НУ
//            u2[i] = u1[i]; //НУ
        }
    }

    for (int i=1; i<n; ++i)
    {
        u1_new[i] = u1[i] + tau*(lambda1*n*n*(u1[i-1]-2*u1[i]+u1[i+1]) + ro + k*u1[i]*u1[i]/u2[i]-gamma*u1[i]);
        u2_new[i] = u2[i] + tau*(lambda2*n*n*(u2[i-1]-2*u2[i]+u2[i+1]) + c*u1[i]*u1[i] - nu*u2[i]);
    }
    u1_new[0] = u1_new[1];   //ГУ
    u1_new[n] = u1_new[n-1]; //ГУ
    u2_new[0] = u2_new[1];   //ГУ
    u2_new[n] = u2_new[n-1]; //ГУ

    currentIter++;
    ui->label_14->setText(QString::number(currentIter));

    plotFunc(x,u1_new);
    plotFunc2(x,u2_new, QPen(Qt::red));
    u1.swap(u1_new);
    u2.swap(u2_new);

    double u1Max=-1, u2Max=-1, u1Min=1e30, u2Min=1e30;
    for (int i=0; i<n+1; ++i)
    {
        if (u1[i]<u1Min)
            u1Min=u1[i];
        if (u2[i]<u2Min)
            u2Min=u2[i];
        if (u1[i]>u1Max)
            u1Max=u1[i];
        if (u2[i]>u2Max)
            u2Max=u2[i];
    }
    ui->label_20->setText(QString("u1 uniformity %1\nu2 uniformity %2").arg(u1Max-u1Min).arg(u2Max-u2Min));

    if (ui->checkBox->checkState() == Qt::Checked)
    {
        table->setRowCount(3);
        table->setColumnCount(n+1);
        for (int i = 0; i<n+1; i++)
        {
            table->setItem(0,i,new QTableWidgetItem(QString::number(x[i])));
            table->setItem(1,i,new QTableWidgetItem(QString::number(u1[i])));
            table->setItem(2,i,new QTableWidgetItem(QString::number(u2[i])));
        }
        table->show();
    }

    if (currentIter==1 || ui->checkBox_2->isChecked())
    {
       this->on_pushButton_Rescale_clicked();
    }
    if (ui->checkBox_3->isChecked())
    {
        ui->graphWidget->yAxis->setRange(ui->doubleSpinBox_minY1->value(),ui->doubleSpinBox_maxY1->value());
    }
    if (ui->checkBox_4->isChecked())
    {
        difference->yAxis->setRange(ui->doubleSpinBox_minY2->value(),ui->doubleSpinBox_maxY2->value());
    }
    //ui->graphWidget->graph(1)->rescaleAxes(true);
    ui->graphWidget->replot();
    difference->replot();
}

void MainWindow::on_pushButton_loadValues_clicked()
{
    currentIter=0;

    n = ui->spinBox->value();
    T = ui->doubleSpinBox_T->value();
    t = ui->spinBox_2->value();
    tau = T/t;
    h = 1.0/n;
    lambda1 = ui->doubleSpinBox_L1->value();
    lambda2 = ui->doubleSpinBox_L2->value();
    ro = ui->doubleSpinBox_ro->value();
    c = ui->doubleSpinBox_c->value();
    gamma = ui->doubleSpinBox_gamma->value();
    k = ui->doubleSpinBox_k->value();
    nu = ui->doubleSpinBox_nu->value();

    x.resize(n+1);
    u1.resize(n+1);
    u2.resize(n+1);
    u1_new.resize(n+1);
    u2_new.resize(n+1);
    x[0]=0;
    for (int i=1; i<n+1; ++i)
    {
      x[i] = i*h;
    }

}

void MainWindow::on_pushButton_2_clicked()
{
    timer->start(ui->horizontalSlider->value());
}

void MainWindow::on_horizontalSlider_valueChanged(int value)
{
    ui->label_13->setText(QString::number(value));
}

void MainWindow::on_pushButton_Rescale_clicked()
{
    if ((difference->graphCount()>0) && (ui->graphWidget->graphCount()>0))
    {
        difference->graph(0)->rescaleAxes();
        ui->graphWidget->graph(0)->rescaleAxes();
        //difference->replot();
        //ui->graphWidget->replot();
    }
}

void MainWindow::updateNumberForTau()
{
    double T = ui->doubleSpinBox_T->value();
    double l1 = ui->doubleSpinBox_L1->value();
    double l2 = ui->doubleSpinBox_L2->value();
    double l = l1>l2 ? l1 : l2;
    if (l<1e-5)
        l=1.0;
    double n = ui->spinBox->value();
    ui->label_6->setText(QString::number(2.0*n*n*T*l*l));

}


void MainWindow::updateSR()
{
    double u1 = (ui->doubleSpinBox_ro->value() + ui->doubleSpinBox_k->value()*ui->doubleSpinBox_nu->value()/ui->doubleSpinBox_c->value())/ui->doubleSpinBox_gamma->value();
    double u2 = u1*u1*ui->doubleSpinBox_c->value()/ui->doubleSpinBox_nu->value();
    QString u1_s = QString::number(u1);
    QString u2_s = QString::number(u2);
    ui->label_18->setText(QString("Equilibrium (") + u1_s + QString("; ") + u2_s + QString(")") );
    this->on_spinBox_3_valueChanged(ui->spinBox_3->value());

}

void MainWindow::on_spinBox_3_valueChanged(int arg1)
{
    double lambda1 = ui->doubleSpinBox_L1->value();
    double lambda2 = ui->doubleSpinBox_L2->value();
    double ro = ui->doubleSpinBox_ro->value();
    double c = ui->doubleSpinBox_c->value();
    double gamma = ui->doubleSpinBox_gamma->value();
    double k = ui->doubleSpinBox_k->value();
    double nu = ui->doubleSpinBox_nu->value();


    double u1 = (ro+k*nu/c)/gamma;
    double u2 = u1*u1*c/nu;
    double sigma = gamma*nu/(c*ro+k*nu);
    double sum = -(lambda1+lambda2)*M_PI*M_PI*arg1*arg1+2*k*sigma-gamma-nu;
    double det = -(lambda2*M_PI*M_PI*arg1*arg1+nu)*(-lambda1*M_PI*M_PI*arg1*arg1+2*k*sigma-gamma) + 2*c*u1*k*sigma*sigma;

    ui->label_19->setText(QString("a+d = ") + QString::number(sum) + QString(";\n ad-bc = ") + QString::number(det));

}

void MainWindow::on_radioButton_1_clicked()
{
    ui->doubleSpinBox_L1->setValue(1);
    ui->doubleSpinBox_L2->setValue(1);
    ui->doubleSpinBox_ro->setValue(1);
    ui->doubleSpinBox_nu->setValue(1);
    ui->doubleSpinBox_c->setValue(1);
    ui->doubleSpinBox_gamma->setValue(1);
    ui->doubleSpinBox_k->setValue(1);
}

void MainWindow::on_radioButton_4_clicked()
{
    ui->doubleSpinBox_L1->setValue(0.1/(M_PI*M_PI));
    ui->doubleSpinBox_L2->setValue(12.2/(1.9*M_PI*M_PI));
    ui->doubleSpinBox_ro->setValue(1);
    ui->doubleSpinBox_nu->setValue(2);
    ui->doubleSpinBox_c->setValue(1);
    ui->doubleSpinBox_gamma->setValue(6);
    ui->doubleSpinBox_k->setValue(1);
}

void MainWindow::on_radioButton_3_clicked()
{
    ui->doubleSpinBox_L1->setValue(1./(30.*M_PI*M_PI));
    ui->doubleSpinBox_L2->setValue(31./(9*M_PI*M_PI));
    ui->doubleSpinBox_ro->setValue(1);
    ui->doubleSpinBox_nu->setValue(1);
    ui->doubleSpinBox_c->setValue(1);
    ui->doubleSpinBox_gamma->setValue(1);
    ui->doubleSpinBox_k->setValue(2);

}

void MainWindow::on_radioButton_2_clicked()
{
    ui->doubleSpinBox_L1->setValue(1);
    ui->doubleSpinBox_L2->setValue(1);
    ui->doubleSpinBox_ro->setValue(1./3.);
    ui->doubleSpinBox_nu->setValue(1);
    ui->doubleSpinBox_c->setValue(1);
    ui->doubleSpinBox_gamma->setValue(2);
    ui->doubleSpinBox_k->setValue(1);

}
